package cn.b.sky.shop.activiti.controller;

import cn.b.sky.shop.activiti.constans.GlobalDefine;
import cn.b.sky.shop.activiti.model.Leave;
import cn.b.sky.shop.activiti.service.impl.LeaveWorkflowService;
import cn.b.sky.common.constants.SystemConstant;
import cn.b.sky.common.model.DWZResult;
import cn.b.sky.common.model.Page;
import cn.b.sky.user.SecurityContextUtil;
import cn.b.sky.user.controller.SecurityController;
import org.activiti.engine.FormService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 请假控制器，包含保存、启动流程
 *
 * @author HenryYan
 */
@Controller
@RequestMapping(value = "/leave/*")
public class LeaveController extends SecurityController {

  private static final Logger LOGGER= LoggerFactory.getLogger(LeaveController.class);

  @Autowired
  protected LeaveWorkflowService workflowService;

  @Autowired
  private RuntimeService runtimeService;

  @Autowired
  protected TaskService taskService;

  @Autowired
  private FormService formService;

  @RequestMapping(value = { "apply", "" })
  public String createForm(Model model, String navTabeId) {
    model.addAttribute("navTabeId", navTabeId);
    return "workflow/barcode";
  }

  /**
   * 保存草稿
   *
   * @param leave
   */
  @RequestMapping(value = { "saveLeave" }, method = { org.springframework.web.bind.annotation.RequestMethod.POST })
  @ResponseBody
  public DWZResult saveLeave(Leave leave, String navTabId) {

    leave.setUserId(SecurityContextUtil.getCurrentUserName());
    workflowService.saveLeave(leave);
    LOGGER.debug("save entity: {}", leave);
    return navTabAjaxDone(navTabId, null, null, null, null, null);
  }

  /**
   * 启动请假流程
   *
   * @param leave
   */
  @RequestMapping(value = { "start" }, method = { org.springframework.web.bind.annotation.RequestMethod.POST })
  public String startWorkflow(Leave leave, String navTabId, HttpServletRequest request) {

    leave.setUserId(SecurityContextUtil.getCurrentUserName());
    workflowService.saveLeave(leave);
    LOGGER.debug("save entity: {}", leave);
    //业务数据
    String businessKey = leave.getBusinessKey();
    //流程key
    String flowMapKey = request.getParameter(GlobalDefine.WorkFlow.PROCESSDEFINITIONID);
    String redirect = SystemConstant.IME_BASEURL + "/workflow/startTask?";
    redirect += GlobalDefine.WorkFlow.BUSINESSKEY + "=" + businessKey;
    redirect += "&flowMap_" + GlobalDefine.WorkFlow.PROCESSDEFINITIONID + "=" + flowMapKey;

    return "redirect:" + redirect;
  }

  /**
   * 任务列表
   *
   * @param leave
   */
  @RequestMapping({ "list/task" })
  public String taskList(Page page, String navTabId, Model model) {
    this.workflowService.findTasks(SecurityContextUtil.getCurrentUserName(), this.getSiteCode(), page);
    model.addAttribute("page", page);
    model.addAttribute(NAVTABID, navTabId);
    return "leave/waittask_list";
  }

  /**
   * 读取运行中的流程实例
   *
   * @return
   */
  @RequestMapping(value = "list/running")
  public ModelAndView runningList(Page page) {
    ModelAndView mav = new ModelAndView("/oa/leave/running");
    this.workflowService.findRunningProcessInstaces(page);
    mav.addObject("page", page);
    return mav;
  }

  /**
   * 读取运行中的流程实例
   *
   * @return
   */
  @RequestMapping(value = "list/finished")
  public ModelAndView finishedList(Page page) {
    ModelAndView mav = new ModelAndView("/oa/leave/finished");
    this.workflowService.findFinishedProcessInstaces(page);
    mav.addObject("page", page);
    return mav;
  }

  /**
   * 签收任务
   */
  @RequestMapping(value = "task/claim/{id}")
  @ResponseBody
  public DWZResult claim(@PathVariable("id") String taskId, String navTabId) {
    String userId = SecurityContextUtil.getCurrentUserName();
    this.workflowService.claimTask(taskId, userId);

    return navTabAjaxDone(navTabId, null, null, null, null, null);
  }

  /**
   * 读取详细数据
   *
   * @param id
   * @return
   */
  @RequestMapping(value = "detail/handleleave")
  public String getLeave(String bussinessKey, String navTabId, Model model) {
    Leave leave = this.workflowService.getLeaveByBussinessKey(bussinessKey);
    model.addAttribute("leave", leave);

    model.addAttribute(NAVTABID, navTabId);
    return "leave/leave_handle";
  }

  /**
   * 
   * <strong>Title : backleave<br></strong>
   * <strong>Description : </strong>销假form<br> 
   * <strong>Create on : 2015-11-2 下午7:43:51<br></strong>
   * <p>
   * @param taskId
   * @param navTabId
   * @param model
   * @return
   * String
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  @RequestMapping({ "detail/backleave" })
  public String backleave(String bussinessKey, String navTabId, Model model) {
    Leave leave = this.workflowService.getLeaveByBussinessKey(bussinessKey);
    model.addAttribute("leave", leave);
    model.addAttribute(NAVTABID, navTabId);
    return "leave/leave_back";
  }

  @RequestMapping({ "detail/repApplyLeave" })
  public String repApplyLeave(String bussinessKey, String navTabId, Model model) {
    Leave leave = this.workflowService.getLeaveByBussinessKey(bussinessKey);
    model.addAttribute("leave", leave);
    model.addAttribute(NAVTABID, navTabId);
    return "leave/leave_reply";
  }

  /**
   *  处理任务
   */
  @RequestMapping({ "handleTask/{id}" })
  public String handleTask(@PathVariable("id") String taskId, String navTabId, Model model) {
    Task task = this.workflowService.getTaskByTaskId(taskId);
    if (task != null) {
      String processInstanceId = task.getProcessInstanceId();
      ProcessInstance processInstance = this.runtimeService.createProcessInstanceQuery()
          .processInstanceId(processInstanceId).active().singleResult();
      String bussinessKey = processInstance.getBusinessKey();
      String processDefinitionId = task.getProcessDefinitionId();

      String redirect = this.formService.getTaskFormKey(processDefinitionId, task.getTaskDefinitionKey());
      return "redirect:/manage/" + redirect + "?taskId=" + taskId + "&navTabId=" + navTabId
          + "&bussinessKey=" + bussinessKey;
    }
    model.addAttribute("message", "此任务没有配置任务表单");
    return "error/500";
  }

  /**
   * 完成任务
   *
   * @param id
   * @return
   * 
   * */

  @RequestMapping(value = { "completeTask" }, method = { RequestMethod.POST, RequestMethod.GET })
  @ResponseBody
  public DWZResult completeTask(String taskId, String navTabId, HttpServletRequest request) {
    if (StringUtils.isBlank(taskId)) {
      return ajaxError("任务id为null");
    }
    try {
      Map<String, Object> flowMap = new HashMap<String, Object>();
      Map<String, Object> operationMap = new HashMap<String, Object>();
      fillOprationMapAndFlowMap(request, flowMap, operationMap);
      this.workflowService.completeTask(taskId, changeMap(flowMap), changeMap(operationMap));
      return dialogAjaxDone(navTabId, null, null, null);
    } catch (Exception e) {
     LOGGER.error("error on complete task {}, variables={}", new Object[] { taskId, e });
    }
    return ajaxError("操作失败!");
  }

 /* @RequestMapping(value = "barcode")
  public void loadBarCode(String barcode, HttpServletResponse response) throws IOException {
    if (!StringUtils.isBlank(barcode)) {
      OutputStream os = response.getOutputStream();
      response.setContentType("image/png");
      BarCodeUtils.generate(barcode, os);
      os.flush();
      os.close();
    }
  }*/

  /**
   * 流程变量按照标准flowMap+"_"+变量名，不然不当做流程变量
   */
  private void fillOprationMapAndFlowMap(HttpServletRequest request, Map<String, Object> flowMap,
                                         Map<String, Object> operationMap) {
    if (flowMap != null && operationMap != null) {
      Map<String, String[]> map = request.getParameterMap();
      Set<Entry<String, String[]>> set = map.entrySet();
      Iterator<Entry<String, String[]>> iterator = set.iterator();
      while (iterator.hasNext()) {
        Entry<String, String[]> entry = iterator.next();
        String key = entry.getKey();
        Object paramenter = request.getParameterValues(key);
        if (key.indexOf(GlobalDefine.WorkFlow.WORKFLOWMAP) == -1) {
          operationMap.put(entry.getKey(), paramenter);
        } else {
          if (key.indexOf("_") != -1) {
            String[] flowKey = key.split("_");
            if (flowKey.length == 2) {
              flowMap.put(flowKey[1], paramenter);
            }
          }
        }
      }
    }
  }

  private Map<String, Object> changeMap(Map<String, Object> map) {
    Set<Entry<String, Object>> mapToSet = map.entrySet();
    Iterator<Entry<String, Object>> iterator = mapToSet.iterator();
    while (iterator.hasNext()) {
      Entry<String, Object> entry = iterator.next();
      Object object = entry.getValue();
      if (object instanceof String[] && ((String[]) object).length == 1) {
        map.put(entry.getKey(), ((String[]) object)[0]);
      }
    }
    return map;
  }
}
